home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Libris Britannia 4
/
science library(b).zip
/
science library(b)
/
CUGUK
/
COMMS
/
C101.ZIP
/
UUPC11XT.ZIP
/
RN
/
NG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-22
|
34KB
|
1,353 lines
/* $Header: E:\SRC\UUPC\RN\RCS\NG.C 1.2 1992/11/22 21:09:09 ahd Exp $
*
* $Log: NG.C $
* Revision 1.2 1992/11/22 21:09:09 ahd
* Back off use of strpool for memory allocation
*
* Revision 1.1 1992/11/21 06:14:58 ahd
* Initial
*
*
* Rev 1.0 18 Nov 1990 0:21:50
* Initial revision.
* Revision 4.3.2.7 90/04/21 14:44:23 sob
* Revised previous patch insure that it does not decrement below zero.
*
* Revision 4.3.2.6 90/03/22 23:04:49 sob
* Fixes provided by Wayne Davison <drivax!davison>
*
* Revision 4.3.2.5 89/12/09 01:18:42 sob
* Fixed a bad call to nntpopen().
*
* Revision 4.3.2.4 89/11/28 01:51:20 sob
* Removed redundant #include directive.
*
* Revision 4.3.2.3 89/11/27 01:31:03 sob
* Altered NNTP code per ideas suggested by Bela Lubkin
* <filbo@gorn.santa-cruz.ca.us>
*
* Revision 4.3.2.2 89/11/26 22:53:35 sob
* Add new patches to make RRN be faster.
*
* Revision 4.3.2.1 89/11/06 00:54:27 sob
* Added RRN support from NNTP 1.5
*
* Revision 4.3.1.6 85/09/10 11:03:42 lwall
* Improved %m in in_char().
*
* Revision 4.3.1.5 85/09/05 12:34:37 lwall
* Catchup command could make unread article count too big.
*
* Revision 4.3.1.4 85/07/23 18:19:46 lwall
* Added MAILCALL environment variable.
*
* Revision 4.3.1.3 85/05/16 16:48:09 lwall
* Fixed unsubsubscribe.
*
* Revision 4.3.1.2 85/05/13 09:29:28 lwall
* Added CUSTOMLINES option.
*
* Revision 4.3.1.1 85/05/10 11:36:00 lwall
* Branch for patches.
*
* Revision 4.3 85/05/01 11:43:43 lwall
* Baseline for release with 4.3bsd.
*
*/
#ifdef msdos
#include <dos.h>
#endif
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include "lib.h"
#include "ssleep.h"
currentfile();
#include "EXTERN.h"
#include "common.h"
#include "rn.h"
#include "term.h"
#include "final.h"
#include "util.h"
#include "artsrch.h"
#include "cheat.h"
#include "help.h"
#include "kfile.h"
#include "rcstuff.h"
#include "head.h"
#include "bits.h"
#include "art.h"
#include "artio.h"
#include "ngstuff.h"
#include "intrp.h"
#include "respond.h"
#include "ngdata.h"
#include "backpage.h"
#include "rcln.h"
#include "last.h"
#include "search.h"
#ifdef SERVER
#include "server.h"
#endif
#include "INTERN.h"
#include "ng.h"
#include "artstate.h" /* somebody has to do it */
/* art_switch() return values */
#define AS_NORM 0
#define AS_INP 1
#define AS_ASK 2
#define AS_CLEAN 3
ART_NUM recent_art = 0; /* previous article #
* for '-' command */
ART_NUM curr_art = 0; /* current article # */
int exit_code = NG_NORM;
void
ng_init()
{
#ifdef KILLFILES
open_kfile(KF_GLOBAL);
#endif
#ifdef CUSTOMLINES
init_compex(&hide_compex);
init_compex(&page_compex);
#endif
}
/* do newsgroup on line ng with name ngname */
/* assumes that we are chdir'ed to SPOOL, and assures that that is
* still true upon return, but chdirs to SPOOL/ngname in between
*
* If you can understand this routine, you understand most of the program.
* The basic structure is:
* for each desired article
* for each desired page
* for each line on page
* if we need another line from file
* get it
* if it's a header line
* do special things
* for each column on page
* put out a character
* end loop
* end loop
* end loop
* end loop
*
* (Actually, the pager is in another routine.)
*
* The chief problem is deciding what is meant by "desired". Most of
* the messiness of this routine is due to the fact that people want
* to do unstructured things all the time. I have used a few judicious
* goto's where I thought it improved readability. The rest of the messiness
* arises from trying to be both space and time efficient. Have fun.
*/
int
do_newsgroup(start_command)
char *start_command; /* command to fake up
* first */
{
#ifdef SERVER
char ser_line[256];
char artname[32];
static long our_pid;
#endif /* SERVER */
char oldmode = mode;
register long i; /* scratch */
int skipstate; /* how many unavailable
* articles */
/* have we skipped already? */
char *whatnext = "%sWhat next? [%s]";
#ifdef SERVER
if (our_pid == 0) /* Agreed, this is gross */
our_pid = getpid();
#endif /* SERVER */
#ifdef ARTSEARCH
srchahead = (scanon && ((ART_NUM) toread[ng]) >= scanon ? -1 : 0);
/* did they say -S? */
#endif
mode = 'a';
recent_art = curr_art = 0;
exit_code = NG_NORM;
#ifdef SERVER
sprintf(ser_line, "GROUP %s", ngname);
put_server(ser_line);
if (get_server(ser_line, sizeof (ser_line)) < 0)
{
fprintf(stderr, "rrn: Unexpected close of server socket.\n");
finalize(1);
}
if (*ser_line != CHAR_OK)
{
if (atoi(ser_line) != ERR_NOGROUP)
fprintf(stderr, "rrn: server response to GROUP %s:\n%s\n",
ngname, ser_line);
return (-1);
}
#else /* not SERVER */
#ifndef msdos
if (eaccess(ngdir, 5))
{ /* directory read
* protected? */
if (eaccess(ngdir, 0))
{
#ifdef VERBOSE
IF(verbose)
printf("\nNewsgroup %s does not have a spool directory!\n",
ngname) FLUSH;
ELSE
#endif
#ifdef TERSE
printf("\nNo spool for %s!\n", ngname) FLUSH;
#endif
#ifdef CATCHUP
catch_up(ng);
#endif
toread[ng] = TR_NONE;
}
else
{
#ifdef VERBOSE
IF(verbose)
printf("\nNewsgroup %s is not currently accessible.\n",
ngname) FLUSH;
ELSE
#endif
#ifdef TERSE
printf("\n%s not readable.\n", ngname) FLUSH;
#endif
toread[ng] = TR_NONE; /* make this newsgroup
* invisible */
/* (temporarily) */
}
mode = oldmode;
return -1;
}
#endif /* msdos */
/* chdir to newsgroup subdirectory */
if (chdir(ngdir))
{
printerr(ngdir);
printf(nocd, ngdir) FLUSH;
mode = oldmode;
return -1;
}
#endif /* SERVER */
#ifdef CACHESUBJ
subj_list = Null(char **);/* no subject list till
* needed */
#endif
/* initialize control bitmap */
if (initctl())
{
mode = oldmode;
return -1;
}
/* FROM HERE ON, RETURN THRU CLEANUP OR WE ARE SCREWED */
in_ng = TRUE; /* tell the world we are
* here */
forcelast = TRUE; /* if 0 unread, do not
* bomb out */
art = firstart;
/* remember what newsgroup we were in for sake of posterity */
writelast();
/* see if there are any special searches to do */
#ifdef KILLFILES
open_kfile(KF_LOCAL);
#ifdef VERBOSE
IF(verbose)
kill_unwanted(firstart, "Looking for articles to kill...\n\n", TRUE);
ELSE
#endif
#ifdef TERSE
kill_unwanted(firstart, "Killing...\n\n", TRUE);
#endif
#endif
/* do they want a special top line? */
firstline = getval("FIRSTLINE", Nullch);
/* custom line suppression, custom page ending */
#ifdef CUSTOMLINES
if (hideline = getval("HIDELINE", Nullch))
compile(&hide_compex, hideline, TRUE, TRUE);
if (pagestop = getval("PAGESTOP", Nullch))
compile(&page_compex, pagestop, TRUE, TRUE);
#endif
/* now read each unread article */
rc_changed = doing_ng = TRUE; /* enter the twilight
* zone */
skipstate = 0; /* we have not skipped
* anything (yet) */
checkcount = 0; /* do not checkpoint for
* a while */
do_fseek = FALSE; /* start 1st article at
* top */
if (art > lastart)
art = firstart; /* init the for loop
* below */
for (; art <= lastart + 1;)
{ /* for each article */
/* do we need to "grow" the newsgroup? */
if (art > lastart || forcegrow)
grow_ctl();
check_first(art); /* make sure firstart is
* still 1st */
if (start_command)
{ /* fake up an initial
* command? */
prompt = whatnext;
strcpy(buf, start_command);
free(start_command);
start_command = Nullch;
art = lastart + 1;
goto article_level;
}
if (art > lastart)
{ /* are we off the end
* still? */
ART_NUM ucount = 0; /* count of unread
* articles left */
for (i = firstart; i <= lastart; i++)
if (!(ctl_read(i)))
ucount++; /* count the unread
* articles */
#ifdef DEBUGGING
/* NOSTRICT */
if (debug && ((ART_NUM) toread[ng]) != ucount)
printf("(toread=%ld sb %ld)", (long) toread[ng], (long) ucount)
FLUSH;
#endif
/* NOSTRICT */
toread[ng] = (ART_UNREAD) ucount; /* this is perhaps
* pointless */
art = lastart + 1; /* keep bitmap
* references sane */
if (art != curr_art)
{
recent_art = curr_art;
/* remember last article # (for '-') */
curr_art = art; /* remember this article
* # */
}
if (erase_screen)
clear(); /* clear the screen */
else
fputs("\n\n", stdout) FLUSH;
#ifdef VERBOSE
IF(verbose)
printf("End of newsgroup %s.", ngname);
/* print pseudo-article */
ELSE
#endif
#ifdef TERSE
printf("End of %s", ngname);
#endif
if (ucount)
{
printf(" (%ld article%s still unread)",
(long) ucount, ucount == 1 ? nullstr : "s");
}
else
{
if (!forcelast)
goto cleanup; /* actually exit
* newsgroup */
}
prompt = whatnext;
#ifdef ARTSEARCH
srchahead = 0; /* no more subject
* search mode */
#endif
fputs("\n\n", stdout) FLUSH;
skipstate = 0; /* back to none skipped */
}
else if (!reread && was_read(art))
{
/* has this article been read? */
art++; /* then skip it */
continue;
}
else if
(!reread && !was_read(art)
#ifdef SERVER
&& nntpopen(art, HEAD) == Nullfp)
{
#else
&& artopen(art) == Nullfp)
{ /* never read it, &
* cannot find it? */
if (errno != ENOENT)
{ /* has it not been
* deleted? */
#ifdef VERBOSE
IF(verbose)
printf("\n(Article %ld exists but is unreadable.)\n",
(long) art) FLUSH;
ELSE
#endif
#ifdef TERSE
printf("\n(%ld unreadable.)\n", (long) art) FLUSH;
#endif
skipstate = 0;
ssleep(2);
}
#endif
switch (skipstate++)
{
case 0:
clear();
#ifdef VERBOSE
IF(verbose)
fputs("Skipping unavailable article", stdout);
ELSE
#endif
#ifdef TERSE
fputs("Skipping", stdout);
#endif
pad(just_a_sec / 3);
break;
case 1:
fputs("..", stdout);
fflush(stdout);
break;
default:
putchar('.');
fflush(stdout);
#ifndef SERVER
#define READDIR
#ifdef READDIR
{ /* fast skip patch */
ART_NUM newart;
if (!(newart = getngmin(".", art)))
newart = lastart + 1;
for (i = art; i < newart; i++)
oneless(i);
art = newart - 1;
}
#endif
#else
{
char ser_line[256];
ART_NUM newart;
put_server("NEXT");
if (get_server(ser_line, sizeof (ser_line)) < 0)
{
fprintf(stderr,
"rrn: unexpected close of server socket.\n");
finalize(1);
}
if (ser_line[0] != CHAR_OK)
newart = lastart + 1;
else
newart = atoi(ser_line + 4);
for (i = art; i < newart; i++)
oneless(i);
art = newart - 1;
}
#endif /* SERVER */
break;
}
oneless(art); /* mark deleted as read */
art++; /* try next article */
continue;
}
else
{ /* we have a real live
* article */
skipstate = 0; /* back to none skipped */
if (art != curr_art)
{
recent_art = curr_art;
/* remember last article # (for '-') */
curr_art = art; /* remember this article
* # */
}
if (!do_fseek)
{ /* starting at top of
* article? */
artline = 0; /* start at the
* beginning */
topline = -1; /* and remember top line
* of screen */
/* (line # within article file) */
}
clear(); /* clear screen */
artopen(art); /* make sure article
* file is open */
if (artfp == Nullfp)
{ /* could not find
* article? */
printf("Article %ld of %s is not available.\n\n",
(long) art, ngname) FLUSH;
prompt = whatnext;
#ifdef ARTSEARCH
srchahead = 0;
#endif
}
else
{ /* found it, so print it */
switch (do_article())
{
case DA_CLEAN: /* quit newsgroup */
goto cleanup;
case DA_TOEND: /* do not mark as read */
goto reask_article;
case DA_RAISE: /* reparse command at
* end of art */
goto article_level;
case DA_NORM: /* normal end of article */
break;
}
}
mark_as_read(art); /* mark current article
* as read */
reread = FALSE;
do_hiding = TRUE;
#ifdef ROTATION
rotate = FALSE;
#endif
}
/* if these gotos bother you, think of this as a little state machine */
reask_article:
#ifdef MAILCALL
setmail();
#endif
setdfltcmd();
#ifdef CLEAREOL
if (erase_screen && can_home_clear)
clear_rest();
#endif /* CLEAREOL */
unflush_output(); /* disable any ^O in
* effect */
standout(); /* enter standout mode */
printf(prompt, mailcall, dfltcmd); /* print prompt,
* whatever it is */
un_standout(); /* leave standout mode */
putchar(' ');
fflush(stdout);
reinp_article:
eat_typeahead();
#ifdef PENDING
look_ahead(); /* see what we can do in
* advance */
if (!input_pending())
collect_subjects(); /* loads subject cache
* until */
/* input is pending */
#endif
getcmd(buf);
if (errno || *buf == '\f')
{
if (LINES < 100 && !int_count)
*buf = '\f'; /* on CONT fake up
* refresh */
else
{
putchar('\n') FLUSH; /* but only on a crt */
goto reask_article;
}
}
article_level:
/* parse and process article level command */
switch (art_switch())
{
case AS_INP: /* multichar command
* rubbed out */
goto reinp_article;
case AS_ASK: /* reprompt "End of
* article..." */
goto reask_article;
case AS_CLEAN: /* exit newsgroup */
goto cleanup;
case AS_NORM: /* display article art */
break;
}
} /* end of article
* selection loop */
/* shut down newsgroup */
cleanup:
#ifdef KILLFILES
kill_unwanted(firstart, "\nCleaning up...\n\n", FALSE);
/* do cleanup from KILL file, if any */
#endif
in_ng = FALSE; /* leave newsgroup state */
if (artfp != Nullfp)
{ /* article still open? */
fclose(artfp); /* close it */
artfp = Nullfp; /* and tell the world */
#ifdef SERVER
sprintf(artname, "/tmp/rrn%ld.%ld", (long) openart, our_pid);
UNLINK(artname);
#endif /* SERVER */
openart = 0;
}
putchar('\n') FLUSH;
yankback(); /* do a Y command */
restore_ng(); /* reconstitute .newsrc
* line */
doing_ng = FALSE; /* tell sig_catcher to
* cool it */
free(ctlarea); /* return the control
* area */
#ifdef CACHESUBJ
if (subj_list)
{
for (i = OFFSET(lastart); i >= 0; --i)
if (subj_list[i])
free(subj_list[i]);
#ifndef lint
free((char *) subj_list);
#endif /* lint */
}
#endif
write_rc(); /* and update .newsrc */
rc_changed = FALSE; /* tell sig_catcher it
* is ok */
if (chdir(spool))
{
printerr(ngdir);
printf(nocd, spool) FLUSH;
sig_catcher(0);
}
#ifdef KILLFILES
if (localkfp)
{
fclose(localkfp);
localkfp = Nullfp;
}
#endif
mode = oldmode;
return exit_code;
} /* Whew! */
/* decide what to do at the end of an article */
int
art_switch()
{
register ART_NUM i;
setdef(buf, dfltcmd);
#ifdef VERIFY
printcmd();
#endif
switch (*buf)
{
case 'p': /* find previous unread
* article */
do
{
if (art <= firstart)
break;
art--;
#ifdef SERVER
} while (was_read(art) || nntpopen(art, HEAD) == Nullfp);
#else
} while (was_read(art) || artopen(art) == Nullfp);
#endif
#ifdef ARTSEARCH
srchahead = 0;
#endif
return AS_NORM;
case 'P': /* goto previous article */
if (art > absfirst)
art--;
else
{
#ifdef VERBOSE
IF(verbose)
fputs("\n\
There are no articles prior to this one.\n\
", stdout) FLUSH;
ELSE
#endif
#ifdef TERSE
fputs("\nNo previous articles\n", stdout) FLUSH;
#endif
return AS_ASK;
}
reread = TRUE;
#ifdef ARTSEARCH
srchahead = 0;
#endif
return AS_NORM;
case '-':
if (recent_art)
{
art = recent_art;
reread = TRUE;
#ifdef ARTSEARCH
srchahead = -(srchahead != 0);
#endif
return AS_NORM;
}
else
{
exit_code = NG_MINUS;
return AS_CLEAN;
}
case 'n': /* find next unread
* article? */
if (art > lastart)
{
if (toread[ng])
art = firstart;
else
return AS_CLEAN;
}
#ifdef ARTSEARCH
else if (scanon && srchahead)
{
*buf = Ctl('n');
goto normal_search;
}
#endif
else
art++;
#ifdef ARTSEARCH
srchahead = 0;
#endif
return AS_NORM;
case 'N': /* goto next article */
if (art > lastart)
art = absfirst;
else
art++;
if (art <= lastart)
reread = TRUE;
#ifdef ARTSEARCH
srchahead = 0;
#endif
return AS_NORM;
case '$':
art = lastart + 1;
forcelast = TRUE;
#ifdef ARTSEARCH
srchahead = 0;
#endif
return AS_NORM;
case '1':
case '2':
case '3': /* goto specified
* article */
case '4':
case '5':
case '6': /* or do something with
* a range */
case '7':
case '8':
case '9':
case '.':
forcelast = TRUE;
switch (numnum())
{
case NN_INP:
return AS_INP;
case NN_ASK:
return AS_ASK;
case NN_REREAD:
reread = TRUE;
#ifdef ARTSEARCH
if (srchahead)
srchahead = -1;
#endif
break;
case NN_NORM:
if (was_read(art))
{
art = firstart;
pad(just_a_sec / 3);
}
else
return AS_ASK;
break;
}
return AS_NORM;
case Ctl('k'):
edit_kfile();
return AS_ASK;
case 'K':
case 'k':
case Ctl('n'):
case Ctl('p'):
case '/':
case '?':
#ifdef ARTSEARCH
normal_search:
{ /* search for article by
* pattern */
char cmd = *buf;
reread = TRUE; /* assume this */
switch (art_search(buf, (sizeof buf), TRUE))
{
case SRCH_ERROR:
return AS_ASK;
case SRCH_ABORT:
return AS_INP;
case SRCH_INTR:
#ifdef VERBOSE
IF(verbose)
printf("\n(Interrupted at article %ld)\n", (long) art) FLUSH;
ELSE
#endif
#ifdef TERSE
printf("\n(Intr at %ld)\n", (long) art) FLUSH;
#endif
art = curr_art;
/* restore to current article */
return AS_ASK;
case SRCH_DONE:
fputs("done\n", stdout) FLUSH;
pad(just_a_sec / 3); /* 1/3 second */
if (srchahead)
art = firstart;
else
art = curr_art;
reread = FALSE;
return AS_NORM;
case SRCH_SUBJDONE:
#ifdef UNDEF
fputs("\n\n\n\nSubject not found.\n", stdout) FLUSH;
pad(just_a_sec / 3); /* 1/3 second */
#endif
art = firstart;
reread = FALSE;
return AS_NORM;
case SRCH_NOTFOUND:
fputs("\n\n\n\nNot found.\n", stdout) FLUSH;
art = curr_art; /* restore to current
* article */
return AS_ASK;
case SRCH_FOUND:
if (cmd == Ctl('n') || cmd == Ctl('p'))
oldsubject = TRUE;
break;
}
return AS_NORM;
}
#else
buf[1] = '\0';
notincl(buf);
return AS_ASK;
#endif
case 'u': /* unsubscribe from this
* newsgroup? */
rcchar[ng] = NEGCHAR;
return AS_CLEAN;
case 'M':
#ifdef DELAYMARK
if (art <= lastart)
{
delay_unmark(art);
printf("\nArticle %ld will return.\n", (long) art) FLUSH;
}
#else
notincl("M");
#endif
return AS_ASK;
case 'm':
if (art <= lastart)
{
unmark_as_read(art);
printf("\nArticle %ld marked as still unread.\n", (long) art) FLUSH;
}
return AS_ASK;
case 'c': /* catch up */
reask_catchup:
#ifdef VERBOSE
IF(verbose)
in_char("\nDo you really want to mark everything as read? [yn] ",
'C');
ELSE
#endif
#ifdef TERSE
in_char("\nReally? [ynh] ", 'C');
#endif
putchar('\n') FLUSH;
setdef(buf, "y");
#ifdef VERIFY
printcmd();
#endif
if (*buf == 'h')
{
#ifdef VERBOSE
IF(verbose)
fputs("\
Type y or SP to mark all articles as read.\n\
Type n to leave articles marked as they are.\n\
Type u to mark everything read and unsubscribe.\n\
", stdout) FLUSH;
ELSE
#endif
#ifdef TERSE
fputs("\
y or SP to mark all read.\n\
n to forget it.\n\
u to mark all and unsubscribe.\n\
", stdout) FLUSH;
#endif
goto reask_catchup;
}
else if (*buf == 'n' || *buf == 'q')
{
return AS_ASK;
}
else if (*buf != 'y' && *buf != 'u')
{
fputs(hforhelp, stdout) FLUSH;
settle_down();
goto reask_catchup;
}
for (i = firstart; i <= lastart; i++)
{
oneless(i); /* mark as read */
}
#ifdef DELAYMARK
if (dmfp)
yankback();
#endif
if (*buf == 'u')
{
rcchar[ng] = NEGCHAR;
return AS_CLEAN;
}
art = lastart + 1;
forcelast = FALSE;
return AS_NORM;
case 'Q':
exit_code = NG_ASK;
/* FALL THROUGH */
case 'q': /* go back up to
* newsgroup level? */
return AS_CLEAN;
case 'j':
putchar('\n') FLUSH;
if (art <= lastart)
mark_as_read(art);
return AS_ASK;
case 'h':
{ /* help? */
int cmd;
if ((cmd = help_art()) > 0)
pushchar(cmd);
return AS_ASK;
}
case '&':
if (switcheroo()) /* get rest of command */
return AS_INP; /* if rubbed out, try
* something else */
return AS_ASK;
case '#':
#ifdef VERBOSE
IF(verbose)
printf("\nThe last article is %ld.\n", (long) lastart) FLUSH;
ELSE
#endif
#ifdef TERSE
printf("\n%ld\n", (long) lastart) FLUSH;
#endif
return AS_ASK;
case '=':
{
char tmpbuf[256];
ART_NUM oldart = art;
int cmd;
char *subjline = getval("SUBJLINE", Nullch);
#ifndef CACHESUBJ
char *s;
#endif
page_init();
#ifdef CACHESUBJ
if (!subj_list)
fetchsubj(art, TRUE, FALSE);
#endif
for (i = firstart; i <= lastart && !int_count; i++)
{
#ifdef CACHESUBJ
if (!was_read(i) &&
(subj_list[OFFSET(i)] != Nullch || fetchsubj(i, FALSE, FALSE)) &&
*subj_list[OFFSET(i)])
{
sprintf(tmpbuf, "%5ld ", i);
if (subjline)
{
art = i;
interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline);
}
else
safecpy(tmpbuf + 6, subj_list[OFFSET(i)],
(sizeof tmpbuf) - 6);
if (cmd = print_lines(tmpbuf, NOMARKING))
{
if (cmd > 0)
pushchar(cmd);
break;
}
}
#else
if (!was_read(i) && (s = fetchsubj(i, FALSE, FALSE)) && *s)
{
sprintf(tmpbuf, "%5ld ", i);
if (subjline)
{ /* probably fetches it
* again! */
art = i;
interp(tmpbuf + 6, (sizeof tmpbuf) - 6, subjline);
}
else
safecpy(tmpbuf + 6, s, (sizeof tmpbuf) - 6);
if (cmd = print_lines(tmpbuf, NOMARKING))
{
if (cmd > 0)
pushchar(cmd);
break;
}
}
#endif
}
int_count = 0;
art = oldart;
return AS_ASK;
}
case '^':
art = firstart;
#ifdef ARTSEARCH
srchahead = 0;
#endif
return AS_NORM;
#if defined(CACHESUBJ) && defined(DEBUGGING)
case 'D':
printf("\nFirst article: %ld\n", (long) firstart) FLUSH;
if (!subj_list)
fetchsubj(art, TRUE, FALSE);
if (subj_list != Null(char **))
{
for (i = 1; i <= lastart && !int_count; i++)
{
if (subj_list[OFFSET(i)])
printf("%5ld %c %s\n",
i, (was_read(i) ? 'y' : 'n'), subj_list[OFFSET(i)]) FLUSH;
}
}
int_count = 0;
return AS_ASK;
#endif
case 'v':
if (art <= lastart)
{
reread = TRUE;
do_hiding = FALSE;
}
return AS_NORM;
#ifdef ROTATION
case Ctl('x'):
#endif
case Ctl('r'):
#ifdef ROTATION
rotate = (*buf == Ctl('x'));
#endif
if (art <= lastart)
reread = TRUE;
return AS_NORM;
#ifdef ROTATION
case 'X':
rotate = !rotate;
/* FALL THROUGH */
#else
case Ctl('x'):
case 'x':
case 'X':
notincl("x");
return AS_ASK;
#endif
case 'l':
case Ctl('l'): /* refresh screen */
if (art <= lastart)
{
reread = TRUE;
clear();
do_fseek = TRUE;
artline = topline;
if (artline < 0)
artline = 0;
}
return AS_NORM;
case 'b':
case Ctl('b'): /* back up a page */
if (art <= lastart)
{
ART_LINE target;
reread = TRUE;
clear();
do_fseek = TRUE;
target = topline - (LINES - 2);
artline = topline;
if (artline > 0)
do
{
artline--;
} while (artline >= 0 && artline > target &&
vrdary(artline - 1) >= 0);
topline = artline;
if (artline < 0)
artline = 0;
}
return AS_NORM;
case '!': /* shell escape */
if (escapade())
return AS_INP;
return AS_ASK;
case 'C':
{
cancel_article();
return AS_ASK;
}
case 'R':
case 'r':
{ /* reply? */
reply();
return AS_ASK;
}
case 'F':
case 'f':
{ /* followup command */
followup();
forcegrow = TRUE; /* recalculate lastart */
return AS_ASK;
}
case '|':
case 'w':
case 'W':
case 's':
case 'S': /* save command */
if (save_article() == SAVE_ABORT)
return AS_INP;
return AS_ASK;
#ifdef DELAYMARK
case 'Y': /* yank back M articles */
yankback();
art = firstart; /* from the beginning */
return AS_NORM; /* pretend nothing
* happened */
#endif
#ifdef STRICTCR
case '\n':
fputs(badcr, stdout) FLUSH;
return AS_ASK;
#endif
default:
printf("\n%s", hforhelp) FLUSH;
settle_down();
return AS_ASK;
}
}
#ifdef MAILCALL
/* see if there is any mail */
void
setmail()
{
if (!(mailcount++))
{
char *mailfile = filexp(getval("MAILFILE", MAILFILE));
if (stat(mailfile, &filestat) < 0 || !filestat.st_size
|| filestat.st_atime > filestat.st_mtime)
mailcall = nullstr;
else
mailcall = getval("MAILCALL", "(Mail) ");
}
mailcount %= 10; /* check every 10
* articles */
}
#endif
void
setdfltcmd()
{
if (toread[ng])
{
#ifdef ARTSEARCH
if (srchahead)
dfltcmd = "^Nnpq";
else
#endif
dfltcmd = "npq";
}
else
{
if (art > lastart)
dfltcmd = "qnp";
else
dfltcmd = "npq";
}
}